<!-- eslint-disable vue/no-v-html -->
<template>
  <div id="config-form" :class="[{ white: props.colorMode === 'white' }]">
    <form ref="$form" class="config-form" @submit.prevent>
      <!-- Config Name Field -->
      <div class="form-group required">
        <label class="form-label">{{ t('pages.configForm.configName') }}</label>
        <div class="form-control">
          <input
            v-model="ruleForm._configName"
            type="text"
            class="form-input"
            :placeholder="t('pages.configForm.configNamePlaceholder')"
            :class="{ error: validationErrors._configName }"
            @input="clearFieldError('_configName')"
          />
          <div v-if="validationErrors._configName" class="error-message">
            {{ validationErrors._configName }}
          </div>
        </div>
      </div>

      <!-- Dynamic Config Fields -->
      <div
        v-for="(item, index) in configList"
        :key="item.name + index"
        class="form-group"
        :class="{ required: item.required }"
      >
        <div class="form-label-wrapper">
          <label class="form-label">{{ item.alias || item.name }}</label>
          <div v-if="showTooltips && item.tips" class="tooltip-wrapper">
            <div class="info-icon" @click="toggleTooltip(item.name + index)">
              <Info :size="20" />
            </div>
            <div
              v-show="visibleTooltips[item.name + index]"
              class="tooltip-content"
              v-html="transformMarkdownToHTML(item.tips)"
            />
          </div>
        </div>

        <div class="form-control">
          <!-- Text/Password Input -->
          <input
            v-if="item.type === 'input' || item.type === 'password'"
            v-model="ruleForm[item.name]"
            type="text"
            class="form-input"
            :placeholder="item.message || item.name"
            :class="{ error: validationErrors[item.name] }"
            @input="clearFieldError(item.name)"
          />

          <!-- Select (Single) -->
          <div v-else-if="item.type === 'list' && item.choices" class="select-wrapper">
            <select
              v-model="ruleForm[item.name]"
              class="form-select"
              :class="{ error: validationErrors[item.name] }"
              @change="clearFieldError(item.name)"
            >
              <option value="" disabled>
                {{ item.message || item.name }}
              </option>
              <option
                v-for="choice in item.choices"
                :key="choice.name || choice.value || choice"
                :value="choice.value || choice"
              >
                {{ choice.name || choice.value || choice }}
              </option>
            </select>
            <div class="select-arrow">
              <ChevronDownIcon :size="20" />
            </div>
          </div>

          <!-- Multi-Select (Checkbox style) -->
          <div v-else-if="item.type === 'checkbox' && item.choices" class="checkbox-group">
            <div v-for="choice in item.choices" :key="choice.value || choice" class="checkbox-item">
              <label class="checkbox-label">
                <input
                  type="checkbox"
                  :value="choice.value || choice"
                  :checked="Array.isArray(ruleForm[item.name]) && ruleForm[item.name].includes(choice.value || choice)"
                  class="checkbox-input"
                  @change="handleCheckboxChange(item.name, choice.value || choice, $event)"
                />
                <span class="checkbox-custom" />
                <span class="checkbox-text">{{ choice.name || choice.value || choice }}</span>
              </label>
            </div>
          </div>

          <!-- Switch/Toggle -->
          <label v-else-if="item.type === 'confirm'" class="switch-label">
            <input
              v-model="ruleForm[item.name]"
              type="checkbox"
              class="switch-input"
              @change="clearFieldError(item.name)"
            />
            <span class="switch-slider">
              <span class="switch-button" />
            </span>
            <span class="switch-text">
              {{ ruleForm[item.name] ? item.confirmText || 'Yes' : item.cancelText || 'No' }}
            </span>
          </label>

          <!-- Validation Error -->
          <div v-if="validationErrors[item.name]" class="error-message">
            {{ validationErrors[item.name] }}
          </div>
        </div>
      </div>
      <slot />
    </form>
  </div>
</template>

<script lang="ts" setup>
import { cloneDeep, union } from 'lodash-es'
import { ChevronDownIcon, Info } from 'lucide-vue-next'
import { marked } from 'marked'
import { reactive, ref, toRefs, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router'

import { getConfig } from '@/utils/dataSender'
import type { IPicGoPluginConfig, IStringKeyMap } from '#/types/types'

interface IProps {
  config: any[]
  type: 'uploader' | 'transformer' | 'plugin'
  id: string
  colorMode?: 'white' | 'dark'
  mode?: 'picbed' | 'plugin'
  showTooltips?: boolean
}

const props = withDefaults(defineProps<IProps>(), {
  colorMode: undefined,
  mode: 'picbed',
  showTooltips: true
})

const $route = useRoute()
const $form = ref<HTMLFormElement>()
const { t } = useI18n()

const configList = ref<IPicGoPluginConfig[]>([])
const ruleForm = reactive<IStringKeyMap>({})
const validationErrors = reactive<IStringKeyMap>({})
const visibleTooltips = reactive<{ [key: string]: boolean }>({})

// Watch for config changes
watch(
  toRefs(props.config),
  (val: IPicGoPluginConfig[]) => {
    handleConfigChange(val)
  },
  {
    deep: true,
    immediate: true
  }
)

function handleConfigChange(val: any) {
  handleConfig(val)
}

function validateField(fieldName: string, value: any, _?: IPicGoPluginConfig): string | null {
  if (fieldName === '_configName') {
    if (!value || value.trim() === '') {
      return 'Configuration name is required'
    }
    return null
  }

  return null
}

function validateForm(): boolean {
  const errors: IStringKeyMap = {}

  const configNameError = validateField('_configName', ruleForm._configName)
  if (configNameError) {
    errors._configName = configNameError
  }

  configList.value.forEach(config => {
    const error = validateField(config.name, ruleForm[config.name], config)
    if (error) {
      errors[config.name] = error
    }
  })

  Object.keys(validationErrors).forEach(key => {
    delete validationErrors[key]
  })

  Object.assign(validationErrors, errors)

  return Object.keys(errors).length === 0
}

function clearFieldError(fieldName: string) {
  if (validationErrors[fieldName]) {
    delete validationErrors[fieldName]
  }
}

function toggleTooltip(key: string) {
  visibleTooltips[key] = !visibleTooltips[key]

  Object.keys(visibleTooltips).forEach(otherKey => {
    if (otherKey !== key) {
      visibleTooltips[otherKey] = false
    }
  })
}

function handleCheckboxChange(fieldName: string, value: any, event: Event) {
  const target = event.target as HTMLInputElement
  const currentValues = Array.isArray(ruleForm[fieldName]) ? [...ruleForm[fieldName]] : []

  if (target.checked) {
    if (!currentValues.includes(value)) {
      currentValues.push(value)
    }
  } else {
    const index = currentValues.indexOf(value)
    if (index > -1) {
      currentValues.splice(index, 1)
    }
  }

  ruleForm[fieldName] = currentValues
  clearFieldError(fieldName)
}

async function validate(): Promise<IStringKeyMap | false> {
  return new Promise(resolve => {
    const isValid = validateForm()
    if (isValid) {
      resolve(ruleForm)
    } else {
      resolve(false)
    }
  })
}

function transformMarkdownToHTML(markdown: string) {
  try {
    return marked.parse(markdown)
  } catch (e) {
    return markdown
  }
}

function getConfigType() {
  switch (props.type) {
    case 'plugin': {
      return props.id
    }
    case 'uploader': {
      return `picBed.${props.id}`
    }
    case 'transformer': {
      return `transformer.${props.id}`
    }
    default:
      return 'unknown'
  }
}

async function handleConfig(val: IPicGoPluginConfig[]) {
  const config = await getCurConfigFormData()
  const configId = props.mode === 'picbed' ? $route.params.configId : null

  Object.assign(ruleForm, config)

  if (val.length > 0) {
    configList.value = cloneDeep(val).map(item => {
      // For plugin mode, don't check configId
      if (props.mode === 'plugin' || !configId) {
        let defaultValue = item.default !== undefined ? item.default : item.type === 'checkbox' ? [] : null

        if (item.type === 'checkbox') {
          const defaults = item.choices?.filter((i: any) => i.checked).map((i: any) => i.value) || []
          defaultValue = union(defaultValue, defaults)
        }

        if (config && config[item.name] !== undefined) {
          defaultValue = config[item.name]
        }

        ruleForm[item.name] = defaultValue
        return item
      }

      let defaultValue = item.default !== undefined ? item.default : item.type === 'checkbox' ? [] : null

      if (item.type === 'checkbox') {
        const defaults = item.choices?.filter((i: any) => i.checked).map((i: any) => i.value) || []
        defaultValue = union(defaultValue, defaults)
      }

      if (config && config[item.name] !== undefined) {
        defaultValue = config[item.name]
      }

      ruleForm[item.name] = defaultValue
      return item
    })
  }
}

async function getCurConfigFormData() {
  if (props.mode === 'plugin') {
    return (await getConfig<IStringKeyMap>(`${props.id}`)) || {}
  } else {
    const configId = $route.params.configId
    const curTypeConfigList = (await getConfig<IStringKeyMap[]>(`uploader.${props.id}.configList`)) || []
    return curTypeConfigList.find(i => i._id === configId) || {}
  }
}

function updateRuleForm(key: string, value: any) {
  try {
    ruleForm[key] = value
    clearFieldError(key)
  } catch (e) {
    console.log(e)
  }
}

defineExpose({
  updateRuleForm,
  validate,
  getConfigType
})
</script>

<style scoped>
#config-form {
  width: 100%;
}

.config-form {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* Form Groups */
.form-group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.form-group.required .form-label::after {
  content: ' *';
  color: var(--color-error, #ef4444);
}

.form-label-wrapper {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.form-label {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-text-primary);
  line-height: 1.25;
}

.form-control {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Tooltip Styles */
.tooltip-wrapper {
  position: relative;
}

.info-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--color-text-secondary);
  transition: var(--transition-fast);
  border-radius: 50%;
  padding: 2px;
}

.info-icon:hover {
  color: var(--color-accent);
  background: rgba(0, 122, 255, 0.1);
}

.tooltip-content {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  min-width: 200px;
  max-width: 300px;
  padding: 0.75rem;
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--color-text-primary);
}

/* Input Styles */
.form-input {
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-elevated);
  color: var(--color-text-primary);
  font-size: 0.875rem;
  font-family: inherit;
  transition: var(--transition-fast);
}

.form-input:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2);
}

.form-input::placeholder {
  color: var(--color-text-secondary);
}

.form-input.error {
  border-color: var(--color-error, #ef4444);
}

.form-input.error:focus {
  box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.2);
}

/* Select Styles */
.select-wrapper {
  position: relative;
}

.form-select {
  width: 100%;
  padding: 0.75rem 2.5rem 0.75rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface-elevated);
  color: var(--color-text-primary);
  font-size: 0.875rem;
  font-family: inherit;
  transition: var(--transition-fast);
  appearance: none;
  cursor: pointer;
}

.form-select:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2);
}

.form-select.error {
  border-color: var(--color-error, #ef4444);
}

.form-select.error:focus {
  box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.2);
}

.select-arrow {
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-secondary);
  pointer-events: none;
  transition: var(--transition-fast);
}

.select-wrapper:hover .select-arrow,
.form-select:focus + .select-arrow {
  color: var(--color-accent);
}

/* Checkbox Group Styles */
.checkbox-group {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.5rem 0;
}

.checkbox-item {
  display: flex;
  align-items: center;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--color-text-primary);
  transition: var(--transition-fast);
}

.checkbox-label:hover {
  color: var(--color-accent);
}

.checkbox-input {
  position: absolute;
  opacity: 0;
  cursor: pointer;
}

.checkbox-custom {
  position: relative;
  width: 1.25rem;
  height: 1.25rem;
  border: 2px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-elevated);
  transition: var(--transition-fast);
  flex-shrink: 0;
}

.checkbox-custom::after {
  content: '';
  position: absolute;
  left: 3px;
  top: 0px;
  width: 6px;
  height: 10px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  opacity: 0;
  transition: var(--transition-fast);
}

.checkbox-input:checked + .checkbox-custom {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.checkbox-input:checked + .checkbox-custom::after {
  opacity: 1;
}

.checkbox-input:focus + .checkbox-custom {
  box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2);
}

.checkbox-text {
  flex: 1;
}

/* Switch Styles */
.switch-label {
  display: flex;
  align-items: center;
  gap: 1rem;
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--color-text-primary);
}

.switch-input {
  position: absolute;
  opacity: 0;
  cursor: pointer;
}

.switch-slider {
  position: relative;
  width: 3rem;
  height: 1.5rem;
  background: var(--color-border);
  border-radius: 0.75rem;
  transition: var(--transition-fast);
  flex-shrink: 0;
}

.switch-button {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 1.25rem;
  height: 1.25rem;
  background: white;
  border-radius: 50%;
  transition: var(--transition-fast);
  box-shadow: var(--shadow-sm);
}

.switch-input:checked + .switch-slider {
  background: var(--color-accent);
}

.switch-input:checked + .switch-slider .switch-button {
  transform: translateX(1.5rem);
}

.switch-input:focus + .switch-slider {
  box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.2);
}

.switch-text {
  font-weight: 500;
  color: var(--color-text-secondary);
}

.switch-input:checked ~ .switch-text {
  color: var(--color-accent);
}

/* Error Message */
.error-message {
  font-size: 0.75rem;
  color: var(--color-error, #ef4444);
  margin-top: 0.25rem;
}

/* White theme adjustments */
.white .form-input,
.white .form-select {
  background: white;
  border-color: #ddd;
}

.white .form-input:focus,
.white .form-select:focus {
  border-color: var(--color-accent);
}

.white .checkbox-custom {
  background: white;
  border-color: #ddd;
}

.white .switch-slider {
  background: #ddd;
}

.white .tooltip-content {
  background: white;
  border-color: #ddd;
}

/* Responsive Design */
@media (max-width: 768px) {
  .config-form {
    gap: 1.25rem;
  }

  .form-input,
  .form-select {
    padding: 0.625rem 0.875rem;
  }

  .form-select {
    padding-right: 2.25rem;
  }

  .tooltip-content {
    min-width: 150px;
    max-width: 250px;
  }
}

/* Dark mode adjustments */
:root.dark .form-input,
:root.auto.dark .form-input,
:root.dark .form-select,
:root.auto.dark .form-select {
  background: var(--color-surface-elevated);
  border-color: var(--color-border);
}

:root.dark .checkbox-custom,
:root.auto.dark .checkbox-custom {
  background: var(--color-surface-elevated);
  border-color: var(--color-border);
}

:root.dark .switch-slider,
:root.auto.dark .switch-slider {
  background: var(--color-border);
}

:root.dark .tooltip-content,
:root.auto.dark .tooltip-content {
  background: var(--color-surface-elevated);
  border-color: var(--color-border);
}

/* Focus styles for accessibility */
.form-input:focus-visible,
.form-select:focus-visible,
.checkbox-input:focus-visible + .checkbox-custom,
.switch-input:focus-visible + .switch-slider,
.info-icon:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
</style>
